#!/bin/sh
# $_id: feedtime.cgi 67 2010-03-08 03:03:49Z lordylordy $
# TV AWK INTERFACE

# (c) Andy Lord andy@lordy.org.uk
#License GPLv3

#
# This is the front-end HTML interface for the command line feedtime.sh script.
# For description of the feedtime application refer to feedtime.sh
# This CGI is only concered with :
# Step 1)Displaying a web page with a form.
# Step 2)Calling feedtime.sh to do stuff based on form contents.
#
# The overal structure of the CGI script is based around two awk scripts.
#
# The first awk script processes any form parameters passed by the web server,
# from the previous request. (if any). This corresponds to Step 2 above.
#
# Because we dont have the luxury of perl CGI module, or PHP, it is all
# done by the awk script. This either parses the QUERY_STRING env sent by 
# the web server, OR it gets the POST data from the TEMP_FILE env.
#
# The form data is converted to an array called query[]. The END clause
# then runs the 'business logic' based on the contents of query[].
# The business logic is served by the feedtime.sh which is a command line 
# script that supports all of the functions of the application.
#
# Relevant Output is passed back to stdout, which is then picked up by 
# the 2nd awk script. This is responsible for displaying the html page,
# and creating the form. (Step1)
#
# To maintain 'session data' the query[] array from awk1 is also passed 
# over to awk2.
# Of particular note is the 'action' parameter which is the main info,
# passed between the two stages.

#GAWK=/share/Apps/gawk/bin/gawk
#if [ -x $GAWK ] ; then
#    AWK="$GAWK --lint"
#    AWK=awk
#else
    AWK=awk
#fi

VERSION=r159
NAME=feedtime.cgi

#Fast platform check without creating a sub-process.
if [ -n "$CPU_MODEL" ] ; then
    arch=nmt200

else
    arch=nmt100
fi

FEEDTIME_HOME="`ls -ld /share | sed 's/.* -> //'`/Apps/feedtime"

self="`echo "$FEEDTIME_HOME" | sed 's@/opt/sybhttpd@http:/@;s/drives/drives:8883/'`"

EXE="$FEEDTIME_HOME/$NAME"

PATH="$FEEDTIME_HOME/bin:$FEEDTIME_HOME/bin/$arch:$PATH"

FEEDTIME_DATADIR="$FEEDTIME_HOME/data"

appname=feedtime
cd "$FEEDTIME_HOME"

feedtime_bin="$FEEDTIME_HOME/$appname.sh"

#METHOD=GET
METHOD=POST

#Processes GET or POST parameters and also outputs them to stdout 
# <name>=<value>
#so display stage can use them.
PROCESS_FORM_VALUES() {
    INPUT=${TEMP_FILE:-/dev/null}

    export UPLOAD_DIR=/share/.nzbget/
    export UPLOAD_OWNER="nmt:nmt"

    if [ ! -d "$UPLOAD_DIR" ] ; then
        mkdir -p "$UPLOAD_DIR"
        chown -R "$UPLOAD_OWNER" "$UPLOAD_DIR"
    fi
        $AWK '

#BEGINAWK
#Set fieldNo = val for all feeds in feed_idList
function setAllItems(file,sep,fieldNo,val,feed_idList,\
feedArray,feed_idArray,id,feed) {

    split(feed_idList,feed_idArray,g_html_sep);

    loadLines(file,sep,feedArray);

    for(feed in feedArray) {
        id = index(feedArray[feed],sep);
        id = substr(feedArray[feed],1,id-1);
        print "CHECKING "id;
        if (feed_idList ~ "\\<"id"\\>" ) {
            print "FOUND "id;
            feedArray[feed] = setDataLine(fieldNo,sep,val,feedArray[feed]);
        }
    }

    saveLines(feedArray,file);
}

#Set fieldNo of feedLine to be val
function setDataLine(fieldNo,sep,val,feedLine,\
feed_fields,i,newLine) {

    split(feedLine,feed_fields,sep);

    feed_fields[fieldNo] = val;

    newLine="";

    for(i = 1 ; i in feed_fields ; i++ ) {
        newLine=newLine sep feed_fields[i];
    }
    newLine = substr(newLine,2);

    print "OLD "feedLine;
    print "NEW "newLine;

    return newLine;
}

function copy(from,to,\
line) {
    while((getline line < from ) > 0) {
        print line > to;
    }
    close(from);
    close(to);
    system("chown -R "ENVIRON["UPLOAD_OWNER"]" "qa(to));
}

function saveLines(feedArray,file,\
i) {
    copy(file,file".old");
    
    for(i in feedArray) {
        if (feedArray[i] != "") {
            print feedArray[i] > file;
        }
    }
    close(file);
}

#Load feeds into array - index 0..n
function loadLines(file,sep,feedArray,\
    feed_count,line) {

    feed_count=0;

    while((getline line < file ) > 0 ) {        
        if (line !~ "^ *#") {
            sub(/\r/,"",line);
            feedArray[feed_count++] = line;
        }
    }
    close(file);
    return feed_count;
}

function addFeed(file,sep,query,id,idList,\
idArr,i,line,f,logf) {
    
    split(idList,idArr,sep);
    line="";
    for(i=1 ; i in idArr ; i++ ) {
         line=line sep query[idArr[i]] ; 
    }
    print id line >> file ;
    close(file);

    initFeed(id);
}

function initFeed(id,\
ff,gr,lr) {
    lr=localRulesFile(id);
    if (!is_file(lr)) {

        ff=feedFolder(id);
        gr=globalRulesFile(id);

        if (system("mkdir -p "qa(ff)) == 0) {
            create_lrule(lr);
            create_grule(gr);
            system("chown -R nmt:nmt "qa(ff));
        }
    }
}

function create_lrule(f) {
    if (!is_file(f)) {
        print "A Show S\nA HD Only Show S?+@hd\nAn SD only show S?+@sd\n" > f;
        close(f);
    }
}

function create_grule(f) {
    if (!is_file(f)) {
        print "-dvdrip-bluray-bdrip-dvdr-complete\n" > f;
        close(f);
    }
}

function is_file(f,\
tmp,err) {
    err = (getline tmp < f );
    if (err == -1) {
        #DEBUG("["f"] doesnt exist");
    } else {
        close(f);
    }
    return (err != -1 );
}

function run_commands(query,\
action,previousaction,feedid) {

    action = query["action"];
    previousaction = query["previousaction"];


    #print "<!-- *****["action"]************* -->"
    if(action == "start" ) {
        docmd("start");

    } else if( action == "stop" ) {
        docmd("stop");

    } else if( action == "reset" ) {
        docmd("reset *");

#    } else if( action == "showhistory" ) {
#
#        docmd("showhistory");
#
    } else if( action == "clearhistory" ) {

        docmd("clearhistory");
        query["action"] = "showhistory";

    } else if( action == "rechecknew" ) {

        docmd("reset *");
        daemon("once *");

    } else if( action == "clearlog" ) {
        docmd("clearlog");
        query["action"] = "showlogs";

    } else if( action == "checknew" ) {

        daemon("once *");

    } else if( action == "updatefeed" ) {

    } else if( previousaction == "editfeeds" && action == "Add" ) {
    
        add_item("editfeed","feedid","newfeed",g_feed_file,g_feed_sep,query,g_feed_fields);

    } else if( previousaction == "editsites" && action == "Add" ) {
    
        add_item("editsite","siteid","newsite",g_site_file,g_site_sep,query,g_site_fields);

    } else if( action == "deletefeeds" ) {

        delete_item(g_feed_file,g_feed_sep,query,"feedlist");
        query["action"] = "editfeeds";

    } else if( action == "deletesites" ) {

        delete_item(g_site_file,g_site_sep,query,"sitelist");
        query["action"] = "editsites";

    } else if( action == "testfeeds" ) {

        daemon("test "html_idList(query["feedlist"],"|"));

    } else if( action == "checkfeeds" ) {

        docmd("once "html_idList(query["feedlist"],"|"));

    } else if( action == "forcefeeds" ) {

        docmd("force "html_idList(query["feedlist"],"|"));

    } else if( action == "skipfeeds" ) {

        docmd("skip "html_idList(query["feedlist"],"|"));

    } else if( previousaction == "editfeeds" && ( action == "enable" || action == "disable" )) {
        
        setAllItems(g_feed_file,g_feed_sep,3, action == "enable" ,query["feedlist"]);
        query["action"] = previousaction;

    } else if( previousaction == "editfeeds" && action == "update" ) {

        update_general(query,g_feed_file,g_feed_sep,"feedids",g_feed_fields);
        query["action"] = "editfeeds";

    } else if( previousaction == "editsites" && action == "update" ) {

        update_general(query,g_site_file,g_site_sep,"siteids",g_site_fields);
        query["action"] = "editsites";

    } else if( previousaction == "editfeed" && action == "save" ) {

            feedid = query["feedid"];

            text2file(query["rules"], localRulesFile(feedid)  );
            text2file(query["grules"], globalRulesFile(feedid) );
            query["action"] = "editfeeds";

    } else if( previousaction ~ "^edit(feed|site)" && action == "back" ) {

            query["action"] = "edit"substr(previousaction,5)"s";

    } else if( action == "configsave" ) {

            config_save(query);


    } else if( action == "download" ) {
        docmd("download \""url_decode(query["url"])"\" "qa(url_decode(query["file"])));
    }
}

function new_id_list(fieldList) {
    gsub(/,/,g_html_sep"new",fieldList);
    return "new"fieldList;
}


function add_item(action,htmlidfield,html_new_prefix,file,sep,query,fieldstr,\
i,feed_id) {
    feed_id = systime();

    addFeed(file,sep,query,feed_id,new_id_list(fieldstr));

    query["action"] = action;
    query[htmlidfield] = feed_id;
    #Copy newfeedxxx to feedxxx.id
    for(i in query) {
        if (i ~ "^"html_new_prefix ) {
            query[substr(i,4) "." feed_id ] = query[i];
        }
    }
}


function delete_item(file,sep,query,htmlid,\
i,id,feedArray,selected) {

    loadLines(file,sep,feedArray);

    getSelected_ids(query,htmlid,selected);

    for(i = 0 ; i in feedArray ; i++ ) {
        
        id = index(feedArray[i],sep);
        
        id = substr(feedArray[i],1,id-1);

        if (id in selected) {
            delete feedArray[i];
            if ( file == g_feed_file ) {
                deleteFeedFolder(id); 
            }
        }
    }
    saveLines(feedArray,file);
}

function update_general(query,file,sep,htmlidstr,fieldstr,\
i,j,fieldcount,feedArray,all_ids,fields,id) {

    fieldcount = split(fieldstr,fields,",");

    split(query[htmlidstr],all_ids,"|");

    for (i = 1 ; i in all_ids ; i++) {
        if (all_ids[i] != "" ) {
            id = all_ids[i];
            feedArray[i] = id ;
            for(j = 1 ; j <= fieldcount ; j++ ) {
                feedArray[i] = feedArray[i] sep query[fields[j]"."id];
            }
        }
    }
    saveLines(feedArray,file);
}
#TODO exlcude option_ variables from self links
function config_save(query,\
option_name,value,oldvalue,real_name) {

    for (option_name in query) {
        if (match(option_name,"^option_")) {
            real_name=substr(option_name,index(option_name,"_")+1);
            value=query[option_name];
            oldvalue=query["orig_"option_name];
            if (value != oldvalue ) {
                docmd(sprintf("set %s \"%s\"",real_name,value));
            }
            delete query[option_name];
            delete query["orig_"option_name];
        }
    }
}

#if a HTML name has multiple values they are separated by \r
#Convert \r to " " so the list can be passed to a script
function html_idList(value,sep) {
    gsub(/\r/,sep,value);
    print "html_idList "value;
    return "\""value"\"";
}

#Get hash of selected feeds - index = id value=1
function getSelected_ids(query,html_id,selected,\
tmp,i) {
    delete selected;
    split(query[html_id],tmp,"[^a-z0-9]+");
    for(i in tmp) {
        selected[tmp[i]] = 1;
    }
}


function daemon(args) {
        print "CMD ARGS: " args ;
        system("DAEMON_DIR=\"'"$FEEDTIME_HOME"'\"  daemon '"$feedtime_bin"' " args " 2>&1");
}
function docmd(args) {
        print "CMD ARGS: " args ;
        system("'"$feedtime_bin"' " args " 2>&1");
}

function parse_query_string(str,dest,\
i,eq,clauses,name,val) {
    if (str != "") {
        # Note that each nzb action has format annn=action 
        # and if there is a a_nnnn=Go then nnnn is the current action.
        # However this may be changed to a mult-action format.
        split(str,clauses,"&");
        for(i in clauses) {
            #TODO Slight bug - cant cope with multi - values.
            eq=index(clauses[i],"=");

            name=url_decode(substr(clauses[i],1,eq-1));
            val=url_decode(substr(clauses[i],eq+1));

            dest[name]=val;
        }
    }
}

function output_values(query,\
i) {
    print "FORM_PARAMS_BEGIN";
    for(i in query) {
        printf "<<%s>>=@@%s@@\n",i,query[i];
    }
    print "FORM_PARAMS_END";
}
#Copy textarea array to a file.
function text2file(text,file) {
    copy(file,file".old");
    printf "%s",text > file;
    close(file);
}

function globalRulesFile(feedid) {
    return feedFolder(feedid)"/tv.global";
}

function localRulesFile(feedid) {
    return feedFolder(feedid)"/tv.list";
}

function feedFolder(feedid) {
    return "'"$FEEDTIME_HOME"'/data/feed_"feedid;
}

function log_delete(msg,\
f) {
    f="'"$FEEDTIME_HOME"'/delete.log";



    print strftime("%y-%m-%d %H:%M",systime()) >> f;
    print msg >> f;
    close(f);
}

function deleteFeedFolder(feed_id,
dir,backupDir) {
    backupDir=qa(feedFolder(feed_id)".old");
    dir=qa(feedFolder(feed_id));
    system("rm -fr "backupDir);
    system("mv -- "dir" "backupDir);
    log_delete("deleted feed "feed_id);
}

function qa(fileName,\
q) {
    q="'"'"'";
    gsub(/'"'"'/,q  "\\" q q , fileName );
    return q fileName q;
}

# Process the POST data into g_query string. No need to change this block
#this needs a re-write
function readFormData(query,
    formPostData,crlf,unix,in_data,start_data,filename,name,cmd,llen,format,boundary,counter,value,urlEncodedInPostData) {

    formPostData=ENVIRON["TEMP_FILE"];
    if (formPostData == "" ) return;

    boundary=ENVIRON["POST_BOUNDARY"]
    urlEncodedInPostData = ( g_http_method=="POST" && ENVIRON["POST_TYPE"] == "application/x-www-form-urlencoded" );
    
    crlf=1
    unix=0
    in_data=-1;
    start_data=-2;
    filename="";
    name="";
    g_has_post_data=1;

    while((getline < formPostData ) > 0 ) {

        if ( counter >= 0 ) {  counter++  ; }

        printf "POST:%s",$0;

        if ( urlEncodedInPostData ) {
            gsub(/[^:]+:/,"");
            parse_query_string($0,query);

        } else if ( index($1,boundary) ) {

            #Process outging item
            if (filename != "" ) {
                close(filename);
                cmd=sprintf("chown %s \"%s\"",ENVIRON["UPLOAD_OWNER"],filename);
                system(cmd);
            } else if (name != "") {
                if(name in query) {
                    #If name appears multiple times - separate with \r
                    query[name] = query[name] "\r" value;
                } else {
                    query[name] = value;
                }
            }

            #Start next item
            counter=0;
            filename="";
            name="";
            value="";

        } else if (counter==1 && index($0,"Content-Disposition: form-data; name=")==1 ) {

            if (match($3,"name=\"[^\"]+\"")) {
                name=substr($3,RSTART+6,RLENGTH-7);
                value="";
            }
            format=crlf;
            filename="";

            if (match($0,"filename=\".*\"")) {

                filename=substr($0,RSTART+10,RLENGTH-11);
                if (filename != "") {
                    filename=sprintf("%s/%s",ENVIRON["UPLOAD_DIR"],filename);
                    printf "" > filename; #Clobber
                }
            }
        } else if (counter==2 && index($0,"Content-Type: application") == 1) {

            format=unix;
            #print "CONTENT: $0"

        } else if (counter>0 && match($0,"^\r$")) {

            #print "END OF HEADER";
            counter=start_data; 

        } else if ( counter<0 ) {

            if (format==crlf ) {
                llen=length($0);
                if (substr($0,llen) == "\r") {
                    $0=substr($0,1,llen-1);
                }
            }

          if (filename != "") {
              printf "%s\n",$0 >> filename;
          } else if (counter == start_data) {
              value=$0;
          } else {
              value=value "\n" $0;
          }
          counter=in_data;
          #print "DATA";
        }
    }
}

#Process input
BEGIN {

    gq="'"'"'";
    print "BEGIN";

    g_feed_fields="feedname,feedenabled,feedurl,feedpriority";
    g_site_fields="sitename,siteenabled,siteuser,sitepassword,siteloginurl,siteloginpost,sitelogouturl,sitesed";

    g_html_sep="|";
    g_feed_sep="|";
    g_site_sep="|";

    g_feedtime_home="'"$FEEDTIME_HOME"'"

    g_feed_file = "'"$FEEDTIME_HOME"'/data/feeds2";
    g_site_file = "'"$FEEDTIME_HOME"'/data/sites2";

    print "QUERY="ENVIRON["QUERY_STRING"];
    parse_query_string(ENVIRON["QUERY_STRING"],g_query);

    readFormData(q2);

    #Merge post data with Get data.
    for(q in q2) {
       g_query[q]=q2[q];
    }

    #This is a straight assignment g_query[name]=value except if the 
    #Name has the form action.val.n2.v2 etc In this case the following values are also set
    # g_query[action]=x and g_query[y]=z
    #This is to allow multiple submit buttons on the same form to pass different information.
    # Another approach (probably the correct one) is to use different forms but this means tracking hidden fields etc
    for(n in g_query) {
        if (index(n,"action.") == 1 ) { 
            split(n,fields,"\\.");
            for(i=1 ; i in fields ; i+=2 ) {
                g_query[fields[i]] = fields[i+1];
            }
            delete g_query[n];
        }
    }
}


function trim(x) {
    sub(/^ +/,"",x);
    sub(/ +$/,"",x);
    return x;
}

END {
    print "END";

    if (g_query["action"] == "Go") {
        #Get real action from the doaction drop down list.
        g_query["action"] = g_query["doaction"];
    }

    if ("action" in g_query) {

        g_query["action"] = trim(g_query["action"]);

        #print "INCOMING: action = "g_query["action"];
        #print "INCOMING: previousaction = "g_query["previousaction"];

        run_commands(g_query);

        #print "OUTGOING: action = "g_query["action"];
        #print "OUTGOING: previousaction = "g_query["previousaction"];
    }

    output_values(g_query);
}

function ORD_INIT(i,hex) {
    for(i=0 ; i < 255 ; i++ ) {
        c = sprintf("%c",i);
        _CHR[i]=c;
        _ORD[c]=i;
        hex=sprintf("%%%02X",i);
        _HTML[c]=hex;
        _HTML[hex]=c;
    }
}
function url_decode(str, i,c) {
  if (!(0 in _CHR)) { ORD_INIT() };
  start=1;
  print "URLIN:" str;
  while ((i=index(substr(str,start),"%")) > 0) {
      i  = (start-1)+i;
      c=toupper(substr(str,i+1,2)); # hex digits
      print "url_decode:"c;
      c=_HTML["%"c];
      print "url_decode:"c;
      str = substr(str,1,i-1) c substr(str,i+3);
      start = i+1;
  }
  print "URLOUT:" str; 
  return str;
}
    ' "$INPUT" 2>&1 
}


#TODO Only get post job info if -l says post jobs queued etc?

RELOAD_PAGE_TO_CLEAR_PARAMS() {
    cat <<HERE
Content-Type: text/html

<html><head><meta http-equiv="REFRESH" content="0;url=$1"></head><body bgcolor="#000055"></body></html>
HERE
exit 0
}

MAIN_PAGE() {

    running=0;

    #f=/share/awk.txt
    PROCESS_FORM_VALUES_OUTPUT_FILE=$TMPDIR/feedtime.cgi.$$

    #Run commands.
    PROCESS_FORM_VALUES > $PROCESS_FORM_VALUES_OUTPUT_FILE

    #Get state of the world...

    if [ -f "$FEEDTIME_DATADIR/$appname.active" ] ; then
        running=1
    fi

    zebedee=0
    if [ -f /opt/sybhttpd/default/zebedee.cgi ] ; then
        zebedee=1
    fi

     $AWK '

function head(\
i) {
                
    print "<head><title>FeedTime '$VERSION' </title>"

    # text-align doesnt work on PCH.
    print "<style type=\"text/css\">";

    if(g_local_browser) {
        print "body { font-family:verdana;arial; font-size:11pt; color:white; background:#000022}";
        print ".log { font-size:10pt ; color:#CCFFFF }";
        print ".metachar { font-size:12pt ; color:#FFFF00 ; background-color:black; font-weight:bold }";
        print "td {color:white }";
        print ".control {color:#FF5555}";
        print ".rule { background-color:#002211; font-size:12px; }"
        print ".menu { background-color:#000044; font-size:10px; }"
        print ".grule { background-color:#220044;  font-size:12px;}"
        print ".main { background-color:#003355; }"
        print "a {color:#EE99FF }";
        print "hr {color:blue }";
        print "h1 {font-size: 14pt }";
        print ".logo { font-size:14pt ; text-decoration:underline; }"
        print ".failedmatch {font-size:10pt ; color:#FFAAAA;}"
        print ".goodmatch {font-size:10pt ; color:#AAFFAA;}"
        print ".optionrow0 { background-color:#005544; }"
        print ".optionrow1 { background-color:#004455; }"
        print ".r3 { background-color:#444444; }"
        print ".r4 { background-color:#555555; }"
        print ".r1 { background-color:#005544; }"
        print ".r2 { background-color:#004455; }"
    } else {
        print "body { font-family:verdana;arial; font-size:11pt; color:black; background:#808080}";
        print ".log { font-size:10pt ; color:black ; }";
        print ".metachar { font-size:12pt ; color:#blue ; background-color:#99Ff99; font-weight:bold }";
        print "td {color:black }";
        print ".control {color:#FF5555}";
        print ".rule { background-color:#EEFFFF; font-size:12px; }"
        print ".menu { background-color:#DDDDFF; font-size:12px; padding:10px; }"
        print ".grule { background-color:#FFEEEE;  font-size:12px;}"
        print ".main { background-color:#F5F5FF; }"
        print "a {color:#990099 ; font-weight:bold; }";
        print "a:hover { background-color:blue ; color:yellow ; font-weight:bold; }";
        print "hr {color:blue }";
        print "h1 {font-size: 14pt }";
        print ".logo { font-size:14pt ; font-weight:bold ; text-decoration:underline; }"
        print ".failedmatch {font-size:10pt ; color:#880000;}"
        print ".goodmatch {font-size:10pt ; color:#008800;}"
        print ".optionrow0 { background-color:#BBFFCC; }"
        print ".optionrow1 { background-color:#BBCCFF; }"
        print ".r3 { background-color:#EEEEEE; }"
        print ".r4 { background-color:#E8E8E8; }"

        print ".r1 { background-color:#eeeeee; }"
        print ".r2 { background-color:#eeeeee; }"

    }
    print ".r1 { font-size:12px; }"
    print ".r2 { font-size:12px; }"
    print ".bodytab { width:95% }\n";
    print "</style>\n";
    print "<link rel=\"shortcut icon\" href=\"site/images/favicon.ico\">\n";

    print "</head>";
    print "<!-- VERSION:'"$VERSION"' -->";
    for (i in ENVIRON) { print "<!-- ENV:" i "=" ENVIRON[i] " -->"; }
    #for (i in g_query) { print "<!-- QUERY:" i "=" g_query[i] " -->"; }
}
function timestamp() {
    return strftime("%H:%M",systime());
}
function start_control_form(previous_action) {
    printf "<form action=\"%s\" enctype=\"multipart/form-data\" method=\"'"$METHOD"'\">\n",g_self;
    print "<table class=\"control\" ><tr>";
    
    # LOGO -------------------------------------
    print "<td valign=\"top\" class=\"menu\" >";
    print "<input type=hidden name=\"previousaction\" value=\""previous_action"\" />";
    print "<center>";
    printf "<span class=\"logo\"><font color=\"#FF5555\">F</font>";
    printf "<font color=\"#5555FF\">eed</font>";
    printf "<font color=\"#FF5555\">T</font>";
    printf "<font color=\"#5555FF\">ime</font></span><br>";
    print "</center><p>";
    menu();
    printf "</td>";

    # ----------------------------------------

    print "<td class=\"main\" width=85% valign=\"top\">";
}

function end_control_form() {
    print "</td></tr></table></form>"
}

function icon_small(name) {
    return icon(name,24);
}

function icon_med(name) {
    return icon(name,32);
}

function icon(name,sz) {
    return "<img src=\"site/images/"name"\" width="sz"px height="sz"px border=0 />";
}

function menu() {
    running='$running';
    zebedee='$zebedee';

    print link("action","showlogs",icon_small("clock.png")"Recent Activity");
    print "<p>" link("action","clearlog",icon_small("eraser.png")" Clear Activity");
    print "<p>";

    if (!running) {
        print link("action","start",icon_small("run.png")" <font color=red>Start service</font>");
    } else {
        print link("action","stop",icon_small("stop.png")" Stop service");
    }

    print "<hr>" link("action","editfeeds",icon_small("feedicon.png")" Manage Feeds");
    print "<p>" link("action","editsites",icon_small("www.png")" Site Definitions");
    print "<p>";
    #print link("action","test","Test Patterns");
    #print "<p>";

    print link("action","config",icon_small("configure.png")" Configure");


    print "<hr>";


    if (zebedee) {
        if (g_local_browser) {
            print "<a href=\"http://127.0.0.1:8883/zebedee.cgi\">Zebedee</a>&nbsp;"
        } else {
            print "<a href=\"./zebedee.cgi\">Go To Zebedee</a>&nbsp;"
        }
    print "<p>";
    }
    print link("action","showhistory",icon_small("date.png")"NZB History");
    print "<p>" link("action","clearhistory",icon_small("eraser.png")" Clear History");
    if (g_local_browser) {
        print "/<a href=\"/webservices_list.html\">Exit</a>"
    }


    print "<br>"small("'$VERSION'");
    if (g_local_browser) {
        print small("Remote Access<br>http://ipaddress:8883/'$appname'.cgi")
    }
}
function small(x) {
    return "<font size=\"-2\">"x"</font>";
}

#Make button labels the same width
function button(name,value) {
    return sprintf("<input class=\"btn\" type=\"submit\" name=\"%s\" value=\"%s\" >\n",name,value);
}
function link(name,value,label) {
    return sprintf("<a href=\"?%s=%s\">%s</a>",name,url_encode(value),label);
}

function link2(name,value,name2,value2,label) {
    return sprintf("<a href=\"?%s=%s&%s=%s\">%s</a>",name,url_encode(value),name2,url_encode(value2),label);
}

function link3(name,value,name2,value2,name3,value3,label) {
    return sprintf("<a href=\"?%s=%s&%s=%s&%s=%s\">%s</a>",name,url_encode(value),name2,url_encode(value2),name3,url_encode(value3),label);
}

function debug(msg) {
    print "<!-- " msg " -->"
}

function globalRulesFile(feedid) {
    return feedFolder(feedid)"/tv.global";
}

function localRulesFile(feedid) {
    return feedFolder(feedid)"/tv.list";
}

function feedFolder(feedid) {
    return g_feedtime_home "/data/feed_"feedid;
}

#Write output
BEGIN {
    gq="'"'"'";
    g_feed_sep="|";
    g_site_sep="|";
    g_html_sep="|";
    g_feedtime_home="'"$FEEDTIME_HOME"'"
    g_feed_file = g_feedtime_home "/data/feeds2";
    g_site_file = g_feedtime_home "/data/sites2";
    print "Content-Type: text/html\n"
    g_local_browser=(ENVIRON["REMOTE_ADDR"] == "127.0.0.1" )
    if (g_local_browser) {
	    g_self="'"$self"'";
    } else {
	    g_self="/feedtime/'$appname'.cgi";
    }
    #print url_encode("a%b?c d"),"<br>"; print url_decode(url_encode("a%b?c d")); exit
}

# Read the current local rules file.
function loadRules(fileName,rule,\
    rule_count,line) {
    rule_count = 0;
    while((getline line < fileName) > 0) {
        rule[rule_count++] = substr(line,index(line,":")+1);
    }
    close(fileName);
    return rule_count;
}

function show_patterns(html_name,text_size,text,rows,\
i) {
    printf "<center>";
    if (g_local_browser) {
        printf "<textarea name=\"%s\" rows=%d cols=32 >",html_name,rows/2;
    } else {
        printf "<textarea name=\"%s\" rows=%d cols=40 >",html_name,rows;
    }
    heapsort(text_size,text,1);
    for(i = 0 ; i < text_size ; i++ ) {
        print text[i];
    }
    printf "</textarea>";
    printf "</center>";
}

function start_page() {
    start_body_table();
    previous_action=g_query["action"];
    start_control_form(previous_action);

    if (previous_action == "editfeeds") {

        show_editfeed_table();

    } else if (previous_action == "editsites") {

        show_editsite_table();

    } else if (previous_action == "editfeed") {

        show_edit_table(g_query["feedid"]);

    } else if (previous_action == "config") {

        content_title(icon_med("configure.png")" Configuration");
        show_config_table();

    } 
}

function is_file(f,\
err) {
    err = ( getline < f );
    if (err != -1 ) close(f);
    return err != -1;
}
function not_empty(f,\
err,line) {
    err = ( getline < f );
    if (err != -1 ) close(f);
    return err == 1;
}

function show_logs(title,fileName,isHistory,\
line,logarr,logidx) {
   FS="\n";

   logidx = 0;
   if (not_empty(fileName".1")) {
       while ((getline line < fileName".1") > 0) {
           logarr[++logidx] = add_log_line(line);
       }
       close(fileName".1");
   }
   if (not_empty(fileName)) {
       while ((getline line < fileName) > 0) {
           logarr[++logidx] = add_log_line(line);
       }
       close(fileName);
   }

   download_fn();


   reverse_log(title,logarr,logidx,isHistory);
}

function download_fn() {
print "<script type=\"text/javascript\">";
print "function dl(nzbname,url) { if (confirm("gq" download "gq" + nzbname + "gq" ? "gq")) { location.replace(url); } }";
print "</script>";
}

function add_log_line(line,\
i,tmp,name,pre,url,post) {

   #replace |http... in logs with a clickable link
   if (( i = match(line,"\\|https?:[^ ]+")) > 0) {
       pre=substr(line,1,RSTART-1);
       post=substr(line,RSTART+RLENGTH);
       split(substr(line,RSTART+1,RLENGTH-1),tmp,"|");
       url=url_encode(tmp[1]);
       name=tmp[2];

       #Remove message part
       if (index(name," req ")) sub(/.* req [0-9]+/,"",name);
       if (index(name,"/")) sub(/[0-9][0-9]\/[0-9][0-9].*/,"",name);

       #Remove dir prefix 
       while (( i = index(name,"/")) > 0 ) {
           name = substr(name,i+1);
       }

       gsub(/[^A-Za-z0-9]+/,".",name);
       if (index(name,".")) {
           sub(/^\./,"",name);
           sub(/\.$/,"",name);
       }

       #remove nzb suffix
       if ( index(name,".nzb") && match(name,"\.nzb$")) {
           name = substr(name,1,RSTART-1);
       }
       name = url_encode(name);

       #line = pre" <a href=\""g_self"?action=download&file="name".nzb&url="url"\">"name"</a>" post;
       line = pre" <a href=\"javascript:dl("gq name gq","gq g_self"?action=download&file="name".nzb&url="url gq")\">"name"</a>" post;
   }
   return line;
}

# Show log back to front. also extract matches and display nicely (sortof)
function reverse_log(title,logarr,logidx,isHistory,\
i,failedmatches,goodmatches) {
   printf "<div class=\"log\">";
   #for (i in ENVIRON) { printf "%s=%s<br>",i,ENVIRON[i]; }
    #Print the log file back to front. If we encounter the seqnece of match patterns convert it to a table.
    content_title(title);
    if (!isHistory) {
        print "<i>Feedtime works in the background. click <a href=\"./feedtime.cgi?action=showlogs\">here</a> to refresh.</i><br>";
    }
    goodmatches="";
    failedmatches="";
    for(i=logidx ; i>=1 ;i--) {
        if(index(logarr[i]," matches") && match(logarr[i],"^[0-9]+ matches")) {
            if(substr(logarr[i],1,2) == "0 ") {
                failedmatches=failedmatches "\n<br>" substr(logarr[i],index(logarr[i],"+")-2);
            } else {
                goodmatches=goodmatches "\n<br>" logarr[i];
            }
        } else {
            showmatches();
            goodmatches="";
            failedmatches="";
            if (logarr[i] != "" ) {
                printf("<br>%s\n",logarr[i]);
            }
        }
    }
    if (logidx == 0 || ( logidx==1 && logarr[1] == "" ) ) {
        print "<br>Empty";
    }
    showmatches();
    goodmatches="";
    failedmatches="";
    printf "</div>";
}

function showmatches(goodmatches,failedmatches) {
     if (goodmatches failedmatches != "") {
         if (goodmatches != "") {
             goodmatches=sprintf("<td class=\"goodmatch\" valign=\"top\"><u><b>Matched</b></u>%s</td>",goodmatches);
         }
         if (failedmatches != "") {
             failedmatches=sprintf("<td class=\"failedmatch\" valign=\"top\"><u><b>No Matches</b></u>%s</td>",failedmatches);
         }
         printf("<br><table><tr>%s%s</tr></table>",failedmatches,goodmatches);
     }
}


function show_config_table() {
    print "<div class=\"log\">";
    system("cd \""g_feedtime_home"\" ; ./options.sh TABLE feedtime.cfg.help data/feedtime.cfg");
    print "</div>"
    print two_buttons("configsave","cancel");
}

function content_title(t) {
    printf "<h1><center>%s</center></h1>",t;
}

function loadLines(file,sep,feedArray,enabled,\
feed_count,details,line,e) {
    feed_count=0;
    print "<!-- loadLines "file"/"sep" -->\n";

    while((e=(getline line < file )) > 0 ) {        

        print "<!-- "e" "line" -->\n";
        if (line !~ "^ *#") {
            
            sub(/\r/,"",line);

            print "<!-- "line" -->\n";

            split(line,details,sep);


            if (enabled == "-" || enabled == details[3] ) {
                feedArray[feed_count] = line;
                feed_count++;
            }
        }
    }
    print "<!-- "e" -->\n";
    if (e >= 0) {
        close(file);
    }
    print "<!-- end loadLines "feed_count" -->\n";
    
    return feed_count+0;
}

function show_editfeed_table(\
feed,idlist,hdr,\
feed_count,feedArray,\
feed_count2,feedArray2) {

    hdr= "<td width=5%>Feed Name</td>";
    hdr = hdr "<td width=*>RSS&nbsp;link</td>";
    hdr = hdr "<td width=5%>Queue</td>";
    hdr = hdr "<td></td>";

    print "<center><b>"icon_med("feedicon.png")" Manage RSS Feeds</b></center>";
    print "<br><table>";
    print "<tr class=r2><td align=right><b>RSS&nbsp;link</b></td><td>";
    print "<ul>";
    print "<li>If a link requires a user/password, create a <a href=\"./feedtime.cgi?action=editsites\">site definition</a> with login details. OR if the site provides a personal rss url, you can use that without the site login definition.</li>";
    print "<li>If the link does not point directly at a downloadable nzb file, use the link transform option in the site definition screen.</li>";
    print "<li>For further information see <a target=_blank href=\"http://code.google.com/p/feedtime/wiki/GettingStarted\">feedtime wiki</a></li>";
    print "</ul></td></tr>";
    print "<tr class=r1><td align=right><b>Queue:</b></td><td>Where to put nzbs in nzbget queue (- will not add the file to the queue. Useful for testing, eg seeing which sites are fastest.</td></tr>"
    print "</table>";


    feed_count = loadLines(g_feed_file,g_feed_sep,feedArray,"-");

    #feed_count2 = loadLines(feedArray2,0);
    #heapsort(feed_count2,feedArray2,2);

    print "<table ><tr class=r4><td width=5%>Action</td>" hdr "</td></tr>";
    idlist = displayFeedLines(feed_count,feedArray);

    idlist = idlist displayFeedLines(feed_count2,feedArray2);

    print "</table>";

    print "<input type=hidden name=feedids value=\""idlist"\" />";
    print "<table><tr>";
    print "<td>"select("doaction","update",\
"update:Apply Changes\
|enable:Enable selected feeds\
|disable:Disable selected feeds\
|testfeeds:Test selected feeds\
|checkfeeds:Check selected feeds for new NZBs\
|skipfeeds:Skip over matches on selected feeds\
|forcefeeds:Force Download on selected feeds\
|nothing:-------------\
|deletefeeds:DELETE selected feeds","")" </td>";
    print "<td>"button("action","Go")"</td>";
    print "</tr></table> If running a test, keep the number of feeds low. ie 1 or 2. Some sites also limit daily downloads.";

    sub(/Feed Name/,"<b>New Feed</b>",hdr);
    print hidden("newfeedenabled","1");
    print "<table ><tr class=r4>"hdr"</tr>";
    print "<tr class=r3><td>"text("newfeedname","","size=10")"</td>";
    print "<td>"text("newfeedurl","","size=80")"</td>";
    print "<td>"select("newfeedpriority","1","1:Top|0:Bottom|2:-","")"</td>";
    print "<td>"button("action","Add")"</td>";
    print "</tr>";
    print "</table>";
}

function show_editsite_table(\
site,idlist,hdr,\
site_count,siteArray,\
site_count2,siteArray2) {

    hdr= "<td width=5%>Domain</td>";
    hdr = hdr "<td width=4%></td>";
    hdr = hdr "<td width=50% ></td>";
    hdr = hdr "<td width=30% ></td>";
    hdr = hdr "<td></td>";

    print "<center><b>"icon_med("www.png")" Site Definitions</b></center>";
    print "<br>Here you can set up login information or download link transform. When processing an RSS url, Feedtime will look at the last two parts of the domain name to see if it is present in this table.<table class=sitedesc>";
    print "<tr class=r1><td align=right width=10%><b>domain</b></td><td width=40%>main domain name (ie site.com NOT www.site.com)</td>";
    print "<td align=right width=10%><b>username/ password</b></td><td width=40%>Add if login required.</td></tr>";
    print "<tr class=r1><td align=right><b>login</b></td><td>The link that performs user login.</td>";
    print "<td align=right><b>form data</b></td><td>login paramters. Use @USERNAME@ and @PASSWORD@ instead of the actual username and password values.</td></tr>";
    print "<tr class=r1><td align=right><b>logout</b></td><td>The logout link</td>";
    print "<td align=right><b>link transform</b></td><td>A small sed script to make rss links downloadable.</td></tr>"
    print "</table>";


    site_count = loadLines(g_site_file,g_site_sep,siteArray,"-");

    #site_count2 = loadLines(siteArray2,0);
    #heapsort(site_count2,siteArray2,2);

    print "<table width=100%><tr class=r4>" hdr "</td></tr>";
    #print "<table width=100%><tr class=r4><td width=5%>Action</td>" hdr "</td></tr>";
    idlist = displaySiteLines(site_count,siteArray);

    idlist = idlist displaySiteLines(site_count2,siteArray2);

    print "</table>";

    print "<input type=hidden name=siteids value=\""idlist"\" />";
    print "<table><tr>";
    print "<td>"select("doaction","update",\
"update:Apply Changes\
|enable:Enable selected sites\
|disable:Disable selected sites\
|nothing:-------------\
|deletesites:DELETE selected sites","")" </td>";
    print "<td>"button("action","Go")"</td>";
    print "</tr></table>";

    sub(/Domain/,"<b>New Domain</b>",hdr);
    print hidden("newsiteenabled","1");
    print "<table width=100%><tr class=r4>"hdr"</tr>";
    print "<tr class=r3><td>"text("newsitename","","size=10")"</td>";
    print "<td>user:"text("newsiteuser","","");
    print "<br>password:"password("newsitepassword","","")"</td>";

    print "<td><table><tr><td> login:</td><td>"text("newsiteloginurl","","size=50")"</td></tr>";
    print "<tr><td>form data:</td><td>"text("newsiteloginpost","","size=50")"</td></tr>";
    print "<tr><td>logout:</td><td>"text("newsitelogouturl","","size=50")"</td></tr></table></td>";

    print "<td>link transform:<br>"text("newsitesed","","size=40")"</td>";

    print "<td>"button("action","Add")"</td>";
    print "</tr>";
    print "</table>";
}

function qa(fileName,\
q) {
    q="'"'"'";
    gsub(/'"'"'/,q  "\\" q q , fileName );
    return q fileName q;
}

function initFeed(id,\
ff,gr,lr) {
    lr=localRulesFile(id);
    if (!is_file(lr)) {

        ff=feedFolder(id);
        gr=globalRulesFile(id);

        if (system("mkdir -p "qa(ff)) == 0 ) {
            create_lrule(lr);
            create_grule(gr);
            system("chown -R nmt:nmt "qa(ff));
        }
    }
}

function create_lrule(f) {
    if (!is_file(f)) {
        print "A Show S\nA HD Only Show S?+@hd\nAn SD only show S?+@sd\n" > f;
        close(f);
    }
}

function create_grule(f) {
    if (!is_file(f)) {
        print "-dvdrip-bluray-bdrip-dvdr-complete\n" > f;
        close(f);
    }
}

function is_file(f,\
tmp,err) {
    err = (getline tmp < f );
    if (err == -1) {
        #DEBUG("["f"] doesnt exist");
    } else {
        close(f);
    }
    return (err != -1 );
}


#Display a feed line 
function displayFeedLines(feed_count,feedArray,\
i,feedDetails,feed_id,feedEnabled,idlist,attr,rule_count,local_rule,grule_count,global_rule) {


    idlist = "";

    heapsort(feed_count,feedArray,"f|2");

    for(i = 0 ; i < feed_count ; i++ ) {
        split(feedArray[i],feedDetails,g_feed_sep);
        feed_id = feedDetails[1];
        feedEnabled = feedDetails[3];
        attr="";
        if (!feedEnabled) {
            attr="disabled";
        }

        initFeed(feed_id);

        print "<tr class=r"((i%2)+3)" >";
        print "<td>"checkbox("feedlist",feed_id,"");
        print hidden("feedenabled."feed_id,feedDetails[3]);
        print "</td>";
        #print "<td><b>"feed_id"</b></td>";
        print "<td>"text("feedname."feed_id,feedDetails[2],"size=10 "attr)"</td>";
        print "<td>"text("feedurl."feed_id,feedDetails[4],"size=80 "attr) "<a target=\"_blank\" href=\""feedDetails[4]"\">view</a></td>";
        print "<td>"select("feedpriority."feed_id,feedDetails[5],"1:Top|0:Bottom|2:-",attr)"</td>";

        rule_count = loadRules(localRulesFile(feed_id),local_rule);
        grule_count = loadRules(globalRulesFile(feed_id),global_rule);
        rule_count="("rule_count"/"grule_count")";
        if (rule_count == "(0/0)") {
            rule_count = "";
        }
        print "<td>"button("action.editfeed.feedid."feed_id,"Filters "rule_count"...")"</td>";
        print "</tr>";
        idlist = idlist g_html_sep feed_id ;
    }
    return idlist;
}

function displaySiteLines(site_count,siteArray,\
i,siteDetails,site_id,siteEnabled,idlist,attr,rule_count,local_rule,grule_count,global_rule) {


    idlist = "";

    heapsort(site_count,siteArray,"f|2");

    for(i = 0 ; i < site_count ; i++ ) {
        split(siteArray[i],siteDetails,g_site_sep);
        site_id = siteDetails[1];
        siteEnabled = siteDetails[3];
        attr="";
        if (!siteEnabled) {
            attr="disabled";
        }

        initFeed(site_id);

        print "<tr class=r"((i%2)+3)" >";
        print "<td>"checkbox("sitelist",site_id,"");
        print hidden("siteenabled."site_id,siteDetails[3]);
        #print "</td><td>";
        #print "<td><b>"site_id"</b></td>";
        print text("sitename."site_id,siteDetails[2],"size=10 "attr)"</td>";

        print "<td>user:"text("siteuser."site_id,siteDetails[4],"size=10 "attr);
        print "<br>password:"password("sitepassword."site_id,siteDetails[5],"size=10 "attr)"</td>";

        print "<td><table><tr><td>login:</td><td>"text("siteloginurl."site_id,siteDetails[6],"size=60 "attr)"</td></tr>";
        print "<tr><td>form data:</td><td>"text("siteloginpost."site_id,siteDetails[7],"size=60 "attr)"</td></tr>";
        print "<tr><td>logout:</td><td>"text("sitelogouturl."site_id,siteDetails[8],"size=60 "attr)"</td></tr></table></td>";

        print "<td>link transform:<br>"text("sitesed."site_id,siteDetails[9],"size=40 "attr)"</td>";

        print "</tr>";
        idlist = idlist g_html_sep site_id ;
    }
    return idlist;
}

function select(name,value,choices,attr,\
i,html,options,o,lbl,found,sep) {

    split(choices,options,"|");
    html = "<select name=\""name"\" "attr" >";
    for(i = 1; i in options ; i++) {
        lbl = o = options[i];
        if ((sep = index(o,":") ) > 0 ) {
            lbl = substr(o,sep+1);
            o = substr(o,1,sep-1);
        }

        if (o == value) {
            found=1;
        }
        html = html "<option value=\""o"\" " (o == value ? "SELECTED=\"SELECTED\"":"") "   >"lbl"</option>";
    }
    if (found == 0 ) { 
        html = html "<option value=\""value"\" SELECTED=\"SELECTED\"  >"value"</option>";
    }
    html = html "</select>";
    if (attr ~ "\\<disabled\\>" ) {
        html = html hidden(name,value);
    }

    return html;
}

function feedValue(id,name) {
    return g_query[name"."id];
}

function hidden(name,value) {
    return "<input type=hidden name=\""name"\" value=\""value"\" />";
}

function checkbox(name,value,attr) {
    return "<input type=checkbox name=\""name"\" value=\""value"\" "attr" />";
}

function text(name,value,attr) {
    return "<input type=text name=\""name"\" value=\""value"\" "attr" />" (match(attr,"disabled") ? hidden(name,value) : "" );
}

function password(name,value,attr) {
    return "<input type=password name=\""name"\" value=\""value"\" "attr" />" (match(attr,"disabled") ? hidden(name,value) : "" );
}

function manageFeed(url,\
id) {
    return "<a href=\""url"\">"url"</a>";
}

function show_edit_table(feed_id,\
global_rule_count,global_rule,rule_count,local_rule) {

    content_title("Edit Listings for feed <a target=\"_blank\" href=\""feedValue(feed_id,"feedurl")"\">"feedValue(feed_id,"feedname")"</a>");

    #print "<p>" link2("action","checknew","feedid",feedid,"Check for new nzbs");
    #print "<p>" link("action","reset","Reset/Rewind feed");

    print "<table width=100%><tr>";

    print "<td class=\"rule\" >"
    print "<u>Feed "feedValue(feed_id,"feedname")" NZB Filters</u><br>"
    if (g_local_browser) {
        print "<b>+text</b> means text must be present eg +720) (default)<br>"
        print "<b>-text</b> means ext must not be present eg -dvdrip)<br>"
        print "More details via <b>remote browser</b><br>"
    }

    print hidden("feedid",feed_id);

    hiddenFeedValues(feed_id);
         
    rule_count = loadRules(localRulesFile(feed_id),local_rule);
    show_patterns("rules",rule_count,local_rule,18);
    print "</td>";
    
    if (!g_local_browser) {
        print "<td class=\"rule\">"
        print "<center><b>NZB Filters</b></center>";
        print "Add TV program patterns on the left.One on each line."
        print "<br>Each line is converted to a pattern which is matched against Subject titles"
        print "<font size=\"-1\"><ul>";
        print "<li>All matching is case insensitive</li>"
        print "<li>A <b>space</b> will match any number of <u><b>non-alphanumeric characters</b></u>.</li>"
        print "<li><b>S1</b> will match S01,<b>S?</b> will match any season</li>"
        print "<li><b>@hd</b> will match 720p, or x264</li>"
        print "<li><b>@sd</b> will match xvid</li>"
        print "<li><b>@se</b> will match season/episode ie sNNeNN, or NxNN</li>"
        print "<li><b>@date</b> will match yyyy.mm.dd</li>"
        print "<li><b>@sedate</b> will match sNNeNN, or NxNN or yyyy.mm.dd</li>"
        print "<li><b>+</b> means the following text <u><b>MUST</b></u> be anywhere in the nzb title.</li>"
        print "<li><b>-</b> means the following text must <u><b>NOT</b></u> be in the title.</li>"
        print "<li><b>*</b> is the wildcard and matches <u><b>any sequence of characters</b></u>. Most of the time (<b>+</b>) is better. Use <b>*</b> only if order is important.</li>"
        print "</ul></font>";
        print "By default patterns start in (+) mode. Examples:"
       print "<p>&quot;<b>Doctor Who-Confidential</b>&quot; Will match &quot;Doctor Who&quot; but not the &quot;confidential&quot; episodes."
       print "<p>The part of a pattern before the first + or - will only match text <i>up to</i> the show number or date. This will usually include the show name but not the episode title. So <b>&quot;pilot&quot;</b> will match &quot;pilot s01e01&quot; but not &quot;lost.s01e01.pilot&quot;. To match the latter, use <b>&quot;+pilot&quot;</b>;"
      print "<p> Also due to popular naming convention <b>&quot;Doctor Who S?&quot;</b> or <b>&quot;Doctor Who @se&quot;</b> will also limit matches to the main series."
      print "<br>Feedtime looks inside each nzb to do intelligent filtering of \"sample\" nzbs. There is no need to filter these manually."
        print "</td>";
    }
    
    print "</tr><tr>" 
    
    print "<td class=\"grule\">"
    print "<center><u>Global Rules</u></center><br>"

    global_rule_count = loadRules(globalRulesFile(feed_id),global_rule);
    show_patterns("grules",global_rule_count,global_rule,4);
    print "</td>";

    if (!g_local_browser) {
        print "<td class=\"grule\">"
        print "<b>Global Rules</b> Add global patterns on the left."
        print "All xvids must match the global patterns<br>"
        print "E.g. For HD only add &quot;<b>+@hd</b>&quot;. For SD add &quot;<b>+@sd&quot;</b><br>"
        print "To filter serialised programs direct from tv broadcasts try &quot;<b>@se-dvdrip</b>&quot;."
        print "</td>"
    }
    
    print "</tr></table>"
    print two_buttons("save","back");
}

function hiddenFeedValues(feed_id,\
feedArr,i) {
    for(i in g_query) {
        if (i ~ "feed.*\\."feed_id) {
            print hidden(i,g_query[i]);
        }
    }
}

function two_buttons(b1,b2) {
    return "<table width=100%><tr><td><center>" button("action",b1) "</center></td><td><center>" button("action",b2) "</center></td></tr></table>";
}

#This is called after the form paramters have been parsed.
function start_body_table() {

    head();

    #PCH styles dont seem to be fully supported. So using old way
    print "<body text=\"#999999\" >";
    print "<table class=\"bodytab\"><tr><td>";
}

function join_query(url,\
u,jq) {
    u="";
    for(jq in g_query) {
        if (u=="") {
            u=url"?"jq"="g_query[jq];
        } else {
            u=u"&"jq"="g_query[jq];
        }
    }
    return u;
}


{ debug($0); }

# Process LOG LINES first -----------------------------------

function font(c,txt) {
   sprintf("<font color=\"%s\">%s</font>",c,txt);
}


/^FORM_PARAMS_BEGIN/,/^FORM_PARAMS_END/ {

        #debug($0);

        if (match($1,"<<.+>>")) {
            name=substr($1,RSTART+2,RLENGTH-4);
            if (match($0,"@@.+@@")) {
                value=substr($0,RSTART+2,RLENGTH-4);
                print "<!-- g_query["name"]=["value"] -->";
                g_query[name]=value;
            }
        }
}


END {

    start_page();

    if (g_query["action"]  ~ "showhistory" ) {

        show_logs(icon_med("date.png")" NZB History",g_feedtime_home "/data/feedtime.history",1);

    } else if (g_query["action"] !~ "save|editfeed|editsite|config|update|enable|disable|delete" ) {

        show_logs(icon_med("clock.png")" Activity",g_feedtime_home "/data/feedtime.out",0);

    }

    end_control_form();
    print "</body>";
    print "</html>";
}

function url_encode(text,\
i,c) {
    if (!(1 in _CHR)) { ORD_INIT(); }

    if (index(text,"%" )) gsub(/%/,_HTML["%"],text);
    
    if (index(text,"?" )) gsub(/\?/,_HTML["?"],text);
    if (index(text,"&" )) gsub(/\&/,_HTML["&"],text);
    if (index(text,":" )) gsub(/:/,_HTML[":"],text);
    if (index(text,"=" )) gsub(/=/,_HTML["="],text);

#    for (i = 1 ; i <= length(text) ; i++ ) {
#        c=substr(text,i,1);
#        if ( _ORD[c] < 20 ) {
#            text = substr(text,1,i-1) _HTML[c] substr(text,i+1);
#            i += 2;
#        }
#    }
    return text;
}

function ORD_INIT(\
i,hex,c) {
    for(i=0 ; i < 255 ; i++ ) {
        c = sprintf("%c",i);
        _CHR[i]=c;
        _ORD[c]=i;
        hex=sprintf("%%%02X",i);
        _HTML[c]=hex;
        _HTML[hex]=c;
    }
}
function url_decode(str,\
start,i,c) {
  start=1;
  #print "URLIN:" str;
  if (!(0 in _CHR)) { ORD_INIT() };

  while ((i=index(substr(str,start),"%")) > 0) {
      i  = (start-1)+i;
      c=toupper(substr(str,i+1,2)); # hex digits
      c=_HTML["%"c];
      str = substr(str,1,i-1) c substr(str,i+3);
      start = i+1;
  }
  #print "URLOUT:" str; 
  return str;
}

#----------------------------------------------------
# HEAPSORT from wikipedia
# Adapted to sorts the data via the index array.
function heapsort (count, data,cmpMethod,\
end,tmp,i,fields,sep,sep1,fldno) {

    if (index(cmpMethod,"f") ) {

        sep="@~";
        sep1=substr(cmpMethod,2,1);

        fldno=substr(cmpMethod,3);

        # extract nth field and put it at the start.
        for(i in data) {
            split(data[i],fields,sep1);
            data[i] = fields[fldno] sep data[i];
        }
    }

    heapify(count,data,cmpMethod);
    end=count-1;
    while (end > 0) {
        tmp=data[0];data[0]=data[end];data[end]=tmp;
        end--;
        siftdown(data,0,end,cmpMethod);
    }

    if (cmpMethod ~ "^f" ) {
        # remove the field we added.
        for(i in data) {
            data[i] = substr(data[i],index(data[i],sep)+length(sep));
        }
    }
}
function heapify (count, data,cmpMethod,\
start) {
    start=int((count-2)/2)
    while (start >= 0) {
        siftdown(data,start,count-1,cmpMethod);
        start--;
    }
}
function siftdown (data,start,end,cmpMethod,\
tmp,root,child) {
    root=start;
    while(root*2+1 <= end) {
        child=root*2+1
        if (child+1 <=end && tolower(data[child]) < tolower(data[child+1])) {
            child++;
        }
        if (cmpMethod == 2 && (data[root]+0 >= data[child]+0)) {
            return;
        } else if (tolower(data[root]) >= tolower(data[child])) {
            return;
        }
        tmp=data[root];data[root]=data[child];data[child]=tmp;
        root=child;
    }
}

#ENDAWK
  ' "$PROCESS_FORM_VALUES_OUTPUT_FILE"
  rm -f "$PROCESS_FORM_VALUES_OUTPUT_FILE"
  #sed 's/</(/g;s/>/)/g;s/^/<br> /' "$PROCESS_FORM_VALUES_OUTPUT_FILE" 
}

## START OF WRAPPER ##
update_cache=0


#Parse any input
TMPDIR=/share/tmp #/tmp has root only permissions on some NMT
if [ ! -d $TMPDIR ] ; then
    mkdir -p $TMPDIR && chown nmt:nmt $TMPDIR && chmod 777 $TMPDIR 
fi

MAIN_PAGE

# vi:syntax=awk:sw=4:et:ts=4
